﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SqlMiM.Common.ViewModel;
using System.Collections.ObjectModel;
using SqlMiM.Common.Commands;
using System.Windows.Input;
using System.Diagnostics;
using System.Windows.Data;
using MvvmFoundation.Wpf;

namespace SqlMiM.SqlMirroring.Options
{
    public class ViewModel : ObservableObject
    {
        private String principalMachineName;
        private PerformanceCounterCategory principalCategory;
        private String mirrorMachineName;
        private PerformanceCounterCategory mirrorCategory;
        private String mirrorInstance;
        private String principalInstance;

        private ObservableCollection<PerformanceCounterCategory> mirrorCategories;
        private ObservableCollection<PerformanceCounterCategory> principalCategories;

        private ObservableCollection<PerformanceCounter> mirrorCounters;
        private ObservableCollection<PerformanceCounter> principalCounters;

        private ObservableCollection<String> mirrorInstances;
        private ObservableCollection<String> principalInstances;

        private RelayCommand selectPrincipalCategories;
        private RelayCommand selectMirrorCategories;
        private RelayCommand selectPrincipalInstances;
        private RelayCommand selectMirrorInstances;
        private RelayCommand selectPrincipalCounters;
        private RelayCommand selectMirrorCounters;


        /// <summary>
        /// Get or Set the Principal Machine Name
        /// </summary>
        public String PrincipalMachineName
        {
            get
            {
                return principalMachineName;
            }
            set
            {
                principalMachineName = value;
                this.RaisePropertyChanged("PrincipalMachineName");
            }
        }

        /// <summary>
        /// Get or Set the performance counter category on Principal machine
        /// </summary>
        public PerformanceCounterCategory PrincipalCategory
        {
            get
            {
                return principalCategory;
            }
            set
            {
                principalCategory = value;
                this.RaisePropertyChanged("PrincipalCategory");
            }
        }

        /// <summary>
        /// Get or Set the performance counter instancename on Principal machine
        /// </summary>
        public String PrincipalInstance
        {
            get
            {
                return principalInstance;
            }
            set
            {
                principalInstance = value;
                this.RaisePropertyChanged("PrincipalInstance");
            }
        }

        /// <summary>
        /// Get or Set the Mirror Machine Name
        /// </summary>
        public String MirrorMachineName
        {
            get { return mirrorMachineName; }
            set
            {
                mirrorMachineName = value;
                this.RaisePropertyChanged("MirrorMachineName");
            }
        }

        /// <summary>
        /// Get or Set the performance counter category on Mirror machine
        /// </summary>
        public PerformanceCounterCategory MirrorCategory
        {
            get { return mirrorCategory; }
            set
            {
                mirrorCategory = value;
                this.RaisePropertyChanged("MirrorCategory");
            }
        }

        /// <summary>
        /// Get or Set the performance counter instancename on Mirror machine
        /// </summary>
        public String MirrorInstance
        {
            get
            {
                return mirrorInstance;
            }
            set
            {
                mirrorInstance = value;
                this.RaisePropertyChanged("MirrorInstance");
            }
        }

        /// <summary>
        /// All available categories on Mirror machine
        /// </summary>
        public ObservableCollection<PerformanceCounterCategory> MirrorCategories
        {
            get { return mirrorCategories; }
            set
            {
                mirrorCategories = value;
                this.RaisePropertyChanged("MirrorCategories");
            }
        }

        /// <summary>
        /// All available counters on Mirror category
        /// </summary>
        public ObservableCollection<PerformanceCounter> MirrorCounters
        {
            get { return mirrorCounters; }
            set
            {
                mirrorCounters = value;
                this.RaisePropertyChanged("MirrorCounters");
            }
        }

        /// <summary>
        /// All available categories on Principal machine
        /// </summary>
        public ObservableCollection<PerformanceCounterCategory> PrincipalCategories
        {
            get { return principalCategories; }
            set
            {
                principalCategories = value;
                this.RaisePropertyChanged("PrincipalCategories");
            }
        }


        /// <summary>
        /// All available counters on Principal category
        /// </summary>
        public ObservableCollection<PerformanceCounter> PrincipalCounters
        {
            get { return principalCounters; }
            set
            {
                principalCounters = value;
                this.RaisePropertyChanged("PrincipalCounters");
            }
        }

        /// <summary>
        /// All available instances on Mirror machine
        /// </summary>
        public ObservableCollection<String> MirrorInstances
        {
            get { return mirrorInstances; }
            set
            {
                mirrorInstances = value;
                this.RaisePropertyChanged("MirrorInstances");
            }
        }

        /// <summary>
        /// All available instances on Principal machine
        /// </summary>
        public ObservableCollection<String> PrincipalInstances
        {
            get { return principalInstances; }
            set
            {
                principalInstances = value;
                this.RaisePropertyChanged("PrincipalInstances");
            }
        }

        #region Command for getting Principal Categories
        /// <summary>
        /// Command to get all available categories on Principal Machine
        /// </summary>
        public ICommand SelectPrincipalCategoriesCommand
        {
            get
            {
                if (selectPrincipalCategories == null)
                {
                    selectPrincipalCategories =
                        new RelayCommand(this.SelectPrincipalCategories, this.CanExecuteSelectPrincipalCategories);
                }
                return selectPrincipalCategories;
            }
        }

        private bool CanExecuteSelectPrincipalCategories()
        {
            return !(String.IsNullOrEmpty(this.PrincipalMachineName));
        }

        public void SelectPrincipalCategories()
        {

            var pcc = PerformanceCounterCategory.GetCategories(this.PrincipalMachineName);

            if (pcc == null || pcc.Length == 0)
                this.PrincipalCategories = null;
            else
            {
                var lst = new List<PerformanceCounterCategory>(pcc);

                var query = lst.Where(p => p.CategoryName.Contains("Database"));

                query = query.OrderBy(p => p.CategoryName);

                this.PrincipalCategories = new ObservableCollection<PerformanceCounterCategory>(query);
                
            }


        }

        #endregion

        #region Command for getting Principal Instances

        /// <summary>
        /// Command to get all available instances on Principal Category
        /// </summary>
        public ICommand SelectPrincipalInstancesCommand
        {
            get
            {
                if (selectPrincipalInstances == null)
                {
                    selectPrincipalInstances =
                        new RelayCommand(this.SelectPrincipalInstances, this.CanExecuteSelectPrincipalInstances);

                }
                return selectPrincipalInstances;
            }
        }

        private bool CanExecuteSelectPrincipalInstances()
        {
            return this.PrincipalCategory != null;
        }

        public void SelectPrincipalInstances()
        {

            var instances = this.PrincipalCategory.GetInstanceNames();

            if (instances == null || instances.Length == 0)
                this.PrincipalInstances = null;
            else
                this.PrincipalInstances = new ObservableCollection<String>(instances);

        }

        #endregion

        #region Command for getting Principal Counters

        /// <summary>
        /// Command to get all available counters on Principal Category + Instance
        /// </summary>
        public ICommand SelectPrincipalCountersCommand
        {
            get
            {
                if (selectPrincipalCounters == null)
                {
                    selectPrincipalCounters =
                        new RelayCommand(this.SelectPrincipalCounters, this.CanExecuteSelectPrincipalCounters);

                }
                return selectPrincipalCounters;
            }
        }

        private bool CanExecuteSelectPrincipalCounters()
        {
            return (this.PrincipalCategory != null && !(String.IsNullOrEmpty(this.PrincipalInstance)));
        }

        public void SelectPrincipalCounters()
        {

            var counters = this.PrincipalCategory.GetCounters(this.PrincipalInstance);

            if (counters == null || counters.Length == 0)
                this.PrincipalCounters = null;
            else
                this.PrincipalCounters = new ObservableCollection<PerformanceCounter>(counters);

        }

        #endregion


        #region Command for getting Mirror Categories
        /// <summary>
        /// Command to get all available categories on Mirror Machine
        /// </summary>
        public ICommand SelectMirrorCategoriesCommand
        {
            get
            {
                if (selectMirrorCategories == null)
                {
                    selectMirrorCategories =
                        new RelayCommand(this.SelectMirrorCategories, this.CanExecuteSelectMirrorCategories);

                }
                return selectMirrorCategories;
            }
        }

        private bool CanExecuteSelectMirrorCategories()
        {
            return !(String.IsNullOrEmpty(this.MirrorMachineName));
        }

        public void SelectMirrorCategories()
        {

            var pcc = PerformanceCounterCategory.GetCategories(this.MirrorMachineName);

            if (pcc == null || pcc.Length == 0)
                this.PrincipalCategories = null;
            else
                this.PrincipalCategories = new ObservableCollection<PerformanceCounterCategory>(pcc);

        }

        #endregion

        #region Command for getting Mirror Instances

        /// <summary>
        /// Command to get all available instances on Mirror Category
        /// </summary>
        public ICommand SelectMirrorInstancesCommand
        {
            get
            {
                if (selectMirrorInstances == null)
                {
                    selectMirrorInstances =
                        new RelayCommand(this.SelectMirrorInstances, this.CanExecuteSelectMirrorInstances);

                }
                return selectMirrorInstances;
            }
        }

        private bool CanExecuteSelectMirrorInstances()
        {
            return this.MirrorCategory != null;
        }

        public void SelectMirrorInstances()
        {

            var instances = this.MirrorCategory.GetInstanceNames();

            if (instances == null || instances.Length == 0)
                this.PrincipalInstances = null;
            else
                this.PrincipalInstances = new ObservableCollection<String>(instances);

        }

        #endregion

        #region Command for getting Mirror Counters

        /// <summary>
        /// Command to get all available counters on Mirror Category + Instance
        /// </summary>
        public ICommand SelectMirrorCountersCommand
        {
            get
            {
                if (selectMirrorCounters == null)
                {
                    selectMirrorCounters =
                        new RelayCommand(this.SelectMirrorCounters, this.CanExecuteSelectMirrorCounters);

                }
                return selectMirrorCounters;
            }
        }

        private bool CanExecuteSelectMirrorCounters()
        {
            return (this.MirrorCategory != null && !(String.IsNullOrEmpty(this.MirrorInstance)));
        }

        public void SelectMirrorCounters()
        {

            var counters = this.MirrorCategory.GetCounters(this.MirrorInstance);

            if (counters == null || counters.Length == 0)
                this.MirrorCounters = null;
            else
                this.MirrorCounters = new ObservableCollection<PerformanceCounter>(counters);

        }

        #endregion


        /// <summary>
        /// Constructor
        /// </summary>
        public ViewModel()
        {
        }


    }
}
